package com.dbappsecurity.jsbridge;

import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.dbappsecurity.jsbridge.Interface.JsPermissionListener;
import com.dbappsecurity.jsbridge.Interface.JsPicDownloadListener;
import com.dbappsecurity.jsbridge.api.JsApiBase;
import com.dbappsecurity.jsbridge.api.JsApiThired;
import com.dbappsecurity.jsbridge.api.JsApiTitlebar;
import com.dbappsecurity.jsbridge.api.JsApiToggle;
import com.dbappsecurity.jsbridge.contract.JsApiBaseContract;
import com.dbappsecurity.jsbridge.contract.JsApiThiredContract;
import com.dbappsecurity.jsbridge.contract.JsApiTitlebarContract;
import com.dbappsecurity.jsbridge.contract.JsApiToggleContract;
import com.dbappsecurity.jsbridge.entity.jsBaseItem;
import com.dbappsecurity.jsbridge.entity.jsThirdTitle;
import com.dbappsecurity.jsbridge.receivers.HomePressedReceiver;
import com.dbappsecurity.jsbridge.receivers.NetworkChangeReceiver;
import com.dbappsecurity.jsbridge.utils.JsAppInfoUtils;
import com.dbappsecurity.jsbridge.utils.JsDeviceInfoUtils;
import com.dbappsecurity.jsbridge.webview.BWebChromeClient;
import com.dbappsecurity.jsbridge.webview.BWebView;
import com.dbappsecurity.jsbridge.webview.BWebViewClient;
import com.dbappsecurity.jsbridge.webview.CompletionHandler;
import com.google.gson.Gson;
import com.jaeger.library.StatusBarUtil;
import com.tbruyelle.rxpermissions2.RxPermissions;
import com.tencent.smtt.sdk.ValueCallback;
import com.tencent.smtt.sdk.WebView;
import io.reactivex.disposables.CompositeDisposable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.json.JSONObject;

import static android.app.Activity.RESULT_OK;

abstract public class JsBaseFragment
    implements JsApiBaseContract, JsApiToggleContract, JsApiTitlebarContract, JsApiThiredContract,
    ViewTreeObserver.OnGlobalLayoutListener {

  abstract protected String loadUrl();

  abstract protected Activity getActivity();

  abstract protected RxPermissions getRxPermissions();

  protected void onPicDownload(String url) {
  }

  public Gson getGson() {
    if (mGson == null) mGson = new Gson();
    return mGson;
  }

  public View mRootView;
  public BWebView mWebView;
  private ProgressBar mProgressBar;
  private AlertDialog mAlertDialog;
  private ProgressDialog mProgressDialog;

  private CompositeDisposable mDisposables = new CompositeDisposable();
  private SharedPreferences mPreferences = null;

  private HomePressedReceiver mHomePressedReceiver;
  private NetworkChangeReceiver mNetworkChangeReceiver;

  private CompletionHandler mAppStartHandler;
  private CompletionHandler mKeyboardSizeHandler;

  private ValueCallback<Uri> uploadMessage;
  private ValueCallback<Uri[]> uploadMessageAboveL;
  private final static int FILE_CHOOSER_RESULT_CODE = 10000;

  private BWebChromeClient mChromeClient;
  private BWebViewClient mViewClient;
  boolean showProgressBar = true;

  private int mVirtualKeyHeigh;

  private Gson mGson;

  //private BWebChromeClient mChromeClient;
  protected JsPermissionListener mPermissionListener = new JsPermissionListener() {
    @Override
    public void rejected(JsPermissionProcessor processor, String permissionName) {
      Toast.makeText(getActivity(), "" + permissionName + " denied", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void rejectedNeverAsk(JsPermissionProcessor processor, String permissionName) {

    }
  };

  private JsPicDownloadListener mPicDownloadListener = new JsPicDownloadListener() {
    @Override
    public void download(Context context, String url) {
      onPicDownload(url);
    }
  };

  public void onViewCreated(View rootView) {
    mRootView = rootView;
    mProgressBar = (ProgressBar) mRootView.findViewById(R.id.progressbar);
    mWebView = (BWebView) mRootView.findViewById(R.id.webview);

    if (mProgressBar==null || mWebView == null) throw new RuntimeException("ProgressBar 和 BWebView 必须存在");

    mWebView.addJavascriptObject(new JsApiBase(this), JsApiBaseContract.TAG);
    mWebView.addJavascriptObject(new JsApiToggle(this), JsApiToggleContract.TAG);
    mWebView.addJavascriptObject(new JsApiTitlebar(this), JsApiTitlebarContract.TAG);
    mWebView.addJavascriptObject(new JsApiThired(this), JsApiThiredContract.TAG);


    mChromeClient = new BWebChromeClient(mWebView) {

      @Override
      public void onProgressChanged(WebView webView, int i) {
        super.onProgressChanged(webView, i);
        if (!showProgressBar) return;
        mProgressBar.setVisibility(i>0&&i<100?View.VISIBLE:View.GONE);
        mProgressBar.setProgress(i);
      }

      @Override
      public void openFileChooser(ValueCallback<Uri> valueCallback, String s, String s1) {
        uploadMessage = valueCallback;
        openImageChooserActivity();
      }

      @Override
      public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> valueCallback,
          FileChooserParams fileChooserParams) {
        uploadMessageAboveL = valueCallback;
        openImageChooserActivity();
        return true;
      }
    };

    mViewClient = BWebViewClient.getInstance(mWebView);
    mWebView.setWebChromeClient(mChromeClient);
    mWebView.setWebViewClient(mViewClient);

    initViewView();

    if (loadUrl() != null && !loadUrl().equals("")) {
      mWebView.loadUrl(loadUrl());
    }
  }

  private void openImageChooserActivity() {
    Intent i = new Intent(Intent.ACTION_GET_CONTENT);
    i.addCategory(Intent.CATEGORY_OPENABLE);
    i.setType("*/*");
    getActivity().startActivityForResult(Intent.createChooser(i, "file Chooser"), FILE_CHOOSER_RESULT_CODE);
  }

  public void initViewView() {

  }

  public void reload(String url){
    if (mWebView!=null&&url!=null)
    mWebView.loadUrl(url);
  }

  public void setWebViewClient(BWebViewClient viewClient) {
    if (viewClient != null) mWebView.setWebViewClient(viewClient);
  }

  public void setWebChromeClient(BWebChromeClient chromeClient) {
    if (chromeClient != null) mWebView.setWebChromeClient(chromeClient);
  }


  //统一的权限管理
  public void requestPermissions(final JsPermissionProcessor jsPermissionProcessor,
      String... permissions) {
    if (jsPermissionProcessor == null) return;
    mDisposables.add(getRxPermissions().requestEach(permissions).subscribe(permission -> {
      Log.i("JsBaseFragment", "Arirus requestPermissions: ");
      if (permission.granted) {
        jsPermissionProcessor.accept(permission.name);
      } else if (permission.shouldShowRequestPermissionRationale) {
        jsPermissionProcessor.rejected(jsPermissionProcessor, permission.name);
      } else {
        jsPermissionProcessor.rejectedNeverAsk(jsPermissionProcessor, permission.name);
      }
    }));
  }

  //基本方法
  @Override
  public void toast(String content, CompletionHandler handler) {
    Toast.makeText(getActivity(), content, Toast.LENGTH_SHORT).show();
  }

  @Override
  public void statusBar(String  color) {
    StatusBarUtil.setColor(getActivity(),Color.parseColor(color),0);
  }

  @Override
  public void menu(String title, List<jsBaseItem> items, CompletionHandler handler) {
    List<String> list = new ArrayList<>();

    for (int i = 0; i < items.size(); i++) {
      list.add(items.get(i).getTitle());
    }
    mAlertDialog =
        JsDialogUtils.getMenu(Objects.requireNonNull(getActivity()), title, list, handler);
    mAlertDialog.show();
  }

  @Override
  public void communicate(String type, String num, String content) {

    final Intent intent = new Intent();
    String permission = Manifest.permission.CALL_PHONE;
    if (type.equals("dial")) {
      intent.setAction(Intent.ACTION_DIAL);
      intent.setData(Uri.parse("tel:" + num));
    } else if (type.equals("sms")) {
      permission = Manifest.permission.SEND_SMS;
      intent.setAction(Intent.ACTION_SENDTO);
      intent.setData(Uri.parse("smsto:" + num));
      intent.putExtra("sms_body", content);
    }

    requestPermissions(new JsPermissionProcessor(mPermissionListener) {
      @Override
      public void accept(String permissionName) {
        getActivity().startActivity(intent);
      }
    }, permission);
  }

  @Override
  public void longPress(String type, String src) {
    JsCustomDialog.start(getActivity(), type, src, mPicDownloadListener);
  }

  @Override
  public void deviceInfo(final CompletionHandler handler) {
    requestPermissions(new JsPermissionProcessor(mPermissionListener) {
      @Override
      public void accept(String permissionName) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("Mac", JsDeviceInfoUtils.getMacAddress());
        map.put("IEMI", JsDeviceInfoUtils.getDeviceID(getActivity()));
        map.put("Model", JsDeviceInfoUtils.getMobilePhoneModel());
        map.put("SystemVersion", JsDeviceInfoUtils.getSystemVersion());
        map.put("msg", "ok");
        handler.complete(new JSONObject(map).toString());
      }
    }, Manifest.permission.READ_PHONE_STATE);
  }

  @Override
  public void appInfo(final CompletionHandler handler) {
    Map<String, String> map = new HashMap<String, String>();
    map.put("Platform", "Android");
    map.put("VersionName", JsAppInfoUtils.getAppVersionName(getActivity().getApplicationContext()));
    map.put("VersionCode", JsAppInfoUtils.getAppVersionCode(getActivity().getApplicationContext()));
    handler.complete(new JSONObject(map).toString());
  }

  @Override
  public void download(String url, String tag) {
    if (tag != null && tag.equals("app")) {
      Intent intent = new Intent();
      intent.setAction("android.intent.action.VIEW");
      Uri content_url = Uri.parse(url);
      intent.setData(content_url);
      getActivity().startActivity(intent);
    }
  }

  @Override
  public void exit() {
    System.exit(0);
  }

  @Override
  public void setSession(Map<String, String> map, CompletionHandler handler) {
    mPreferences = getActivity().getPreferences(Context.MODE_PRIVATE);
    for (String key : map.keySet()) {
      mPreferences.edit().putString(key, map.get(key)).apply();
    }

    handler.complete(success());
  }

  @Override
  public void getSession(List<String> list, CompletionHandler handler) {
    mPreferences = getActivity().getPreferences(Context.MODE_PRIVATE);

    Map<String, String> res = new HashMap<>();
    Map<String, String> res1 = new HashMap<>();

    for (String st : list) {
      res.put(st, mPreferences.getString(st, ""));
    }
    res1.put("data", getGson().toJson(res));
    handler.complete(getGson().toJson(res1));
  }

  @Override
  public void showPdf(String url, CompletionHandler handler) {

  }

  //Toggle 方法
  @Override
  public void loading(String toggle, String content, CompletionHandler handler) {
    if (toggle.equals("0")) {
      if (content == null) content = "加载中，稍后";
        mProgressDialog = ProgressDialog.show(getActivity(), null, content + "", true, true);
        mProgressDialog.setCanceledOnTouchOutside(false);
    } else {
      if (mProgressDialog!=null) {
        mProgressDialog.dismiss();
        mProgressDialog = null;
      }
    }
    handler.complete(success());
  }

  @Override
  public void appStart(String tag, CompletionHandler handler) {
    if (tag.equals("0")) {
      mAppStartHandler = handler;
    } else if (tag.equals("1")) {
      if (mAppStartHandler == null) {
        return;
      }
      handler.complete(success());
      mAppStartHandler = null;
    }
  }

  @Override
  public void homeClick(String tag, CompletionHandler handler) {
    if (tag.equals("0")) {
      if (mHomePressedReceiver != null) {
        return;
      }
      mHomePressedReceiver = new HomePressedReceiver(handler);
      getActivity().registerReceiver(mHomePressedReceiver,
          new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
    } else if (tag.equals("1")) {
      if (mHomePressedReceiver == null) {
        return;
      }
      getActivity().unregisterReceiver(mHomePressedReceiver);
      mHomePressedReceiver = null;
      handler.complete(success());
    }
  }

  @Override
  public void pushService(String tag, CompletionHandler handler) {
    if (tag.equals("0")) {
      handler.complete(success());
    } else if (tag.equals("1")) {
      handler.complete(success());
    }
  }


  @Override
  public void keyboardSize(String tag, CompletionHandler handler) {
    if (tag.equals("0")) {
      mKeyboardSizeHandler = handler;
      mVirtualKeyHeigh = getVirtualBarHeigh(getActivity());
      mRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
    } else if (tag.equals("1")) {
      if (mKeyboardSizeHandler == null) return;
      mRootView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
      mKeyboardSizeHandler = null;
      handler.complete(success());
    }
  }

  @Override
  public void networkChange(String tag, CompletionHandler handler) {
    if (tag.equals("0")) {
      if (mNetworkChangeReceiver != null) {
        return;
      }
      mNetworkChangeReceiver = new NetworkChangeReceiver(handler);
      IntentFilter filter = new IntentFilter();
      filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
      getActivity().registerReceiver(mNetworkChangeReceiver, filter);
    } else if (tag.equals("1")) {
      if (mNetworkChangeReceiver == null) return;
      getActivity().unregisterReceiver(mNetworkChangeReceiver);
      mNetworkChangeReceiver = null;
      handler.complete(success());
    }
  }

  @Override
  public void progressBar(String tag, CompletionHandler handler) {
    showProgressBar = tag.equals("0");
    handler.complete(success());
  }


  public void onResume() {
    if (null != mAppStartHandler) {
      mAppStartHandler.setProgressData(success());
    }
  }

  public void onPause() {
    mDisposables.clear();
    if (mAlertDialog != null && mAlertDialog.isShowing()) {
      mAlertDialog.dismiss();
    }
    if (mProgressDialog != null && mProgressDialog.isShowing()) {
      mProgressDialog.dismiss();
    }
  }

  public void onDestroyView() {
    if (mPreferences!=null) mPreferences.edit().clear().apply();
    if (mNetworkChangeReceiver != null) getActivity().unregisterReceiver(mNetworkChangeReceiver);
    if (mHomePressedReceiver != null) getActivity().unregisterReceiver(mHomePressedReceiver);
  }

  public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == FILE_CHOOSER_RESULT_CODE) {
      if (null == uploadMessage && null == uploadMessageAboveL) return;
      Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
      if (uploadMessageAboveL != null) {
        onActivityResultAboveL(requestCode, resultCode, data);
      } else if (uploadMessage != null) {
        uploadMessage.onReceiveValue(result);
        uploadMessage = null;
      }
    }
  }

  @TargetApi(Build.VERSION_CODES.LOLLIPOP)
  private void onActivityResultAboveL(int requestCode, int resultCode, Intent intent) {
    if (requestCode != FILE_CHOOSER_RESULT_CODE || uploadMessageAboveL == null) {
      return;
    }
    Uri[] results = null;
    if (resultCode == Activity.RESULT_OK) {
      if (intent != null) {
        String dataString = intent.getDataString();
        ClipData clipData = intent.getClipData();
        if (clipData != null) {
          results = new Uri[clipData.getItemCount()];
          for (int i = 0; i < clipData.getItemCount(); i++) {
            ClipData.Item item = clipData.getItemAt(i);
            results[i] = item.getUri();
          }
        }
        if (dataString != null) {
          results = new Uri[] { Uri.parse(dataString) };
        }
      }
    }
    uploadMessageAboveL.onReceiveValue(results);
    uploadMessageAboveL = null;
  }

  @Override
  public void scan(jsThirdTitle jsthirdtitle, CompletionHandler handler) {
    Toast.makeText(getActivity(), "客户端未实现", Toast.LENGTH_SHORT).show();
    Log.i("JsBaseFragment", "Arirus scan: 客户端未实现");
  }

  @Override
  public void share(JSONObject jsonObject, CompletionHandler handler) {
    Toast.makeText(getActivity(), "客户端未实现", Toast.LENGTH_SHORT).show();
    Log.i("JsBaseFragment", "Arirus scan: 客户端未实现");
  }

  @Override
  public void location(CompletionHandler handler) {
    Toast.makeText(getActivity(), "客户端未实现", Toast.LENGTH_SHORT).show();

  }

  @Override
  public void pushTags(List<String> tags, CompletionHandler handler) {
    Toast.makeText(getActivity(), "客户端未实现", Toast.LENGTH_SHORT).show();

  }

  @Override
  public void pushAlias(String alias, CompletionHandler handler) {
    Toast.makeText(getActivity(), "客户端未实现", Toast.LENGTH_SHORT).show();

  }

  @Override
  public void pushClean(CompletionHandler handler) {
    Toast.makeText(getActivity(), "客户端未实现", Toast.LENGTH_SHORT).show();

  }

  @Override
  public void chooseImage(JSONObject jsonObject, CompletionHandler handler) {
    Toast.makeText(getActivity(), "客户端未实现", Toast.LENGTH_SHORT).show();

  }

  @Override
  public void thirdPartyWeb(jsThirdTitle jsthirdtitle, CompletionHandler handler) {
    Toast.makeText(getActivity(), "客户端未实现", Toast.LENGTH_SHORT).show();

  }

  @Override
  public void clickCustom(String index, CompletionHandler handler) {

    Toast.makeText(getActivity(), "客户端未实现", Toast.LENGTH_SHORT).show();
  }

  @Override
  public void buttons(List<jsBaseItem> items, String type, CompletionHandler handler) {
    Toast.makeText(getActivity(), "客户端未实现", Toast.LENGTH_SHORT).show();

  }

  @Override
  public void menu(List<jsBaseItem> items, CompletionHandler handler) {
    Toast.makeText(getActivity(), "客户端未实现", Toast.LENGTH_SHORT).show();

  }

  @Override
  public void title(String title) {

    Toast.makeText(getActivity(), "客户端未实现", Toast.LENGTH_SHORT).show();
  }

  @Override
  public void color(int color) {

    Toast.makeText(getActivity(), "客户端未实现", Toast.LENGTH_SHORT).show();
  }

  @Override
  public void titleBar(String toggle, CompletionHandler handler) {

    Toast.makeText(getActivity(), "客户端未实现", Toast.LENGTH_SHORT).show();
  }

  @Override
  public void titleClick(String toggle, CompletionHandler handler) {

    Toast.makeText(getActivity(), "客户端未实现", Toast.LENGTH_SHORT).show();
  }

  public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (event.getAction()== KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()){
      mWebView.goBack();
      return true;
    }
    return false;
  }

  public int getVirtualBarHeigh(Context context) {
    int vh = 0;
    if (context == null) return vh;
    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = windowManager.getDefaultDisplay();
    DisplayMetrics dm = new DisplayMetrics();
    try {
      @SuppressWarnings("rawtypes") Class c = Class.forName("android.view.Display");
      @SuppressWarnings("unchecked") Method method =
          c.getMethod("getRealMetrics", DisplayMetrics.class);
      method.invoke(display, dm);
      vh = dm.heightPixels - windowManager.getDefaultDisplay().getHeight();
    } catch (Exception e) {
      e.printStackTrace();
    }
    return vh;
  }

  @Override
  public void onGlobalLayout() {
    Rect r = new Rect();
    //获取当前界面可视部分
    getActivity().getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
    //获取屏幕的高度
    int screenHeight = getActivity().getWindow().getDecorView().getRootView().getHeight();
    //此处就是用来获取键盘的高度的， 在键盘没有弹出的时候 此高度为0 键盘弹出的时候为一个正数
    int heightDifference = screenHeight - r.bottom;
    Log.d("Keyboard Size", "Size: " + heightDifference);
    Log.d("Keyboard ", "Size: " + getVirtualBarHeigh(getActivity()));
    if (heightDifference - mVirtualKeyHeigh > 0) {
      Map<String, String> map = new HashMap<>();
      map.put("height", "" + (heightDifference - mVirtualKeyHeigh));
      JSONObject jsonObject = new JSONObject(map);
      mKeyboardSizeHandler.setProgressData(jsonObject.toString());
    }
  }

  // 成功的回调
  JSONObject success = null;
  protected synchronized String success(){
    if (success == null) {
      Map<String, String> map = new HashMap<>();
      map.put("msg", "ok");
      success = new JSONObject(map);
    }
    return success.toString();
  }

  // 失败的回调
  JSONObject failed = null;
  protected synchronized String  failed(){
    if (failed == null) {
      Map<String, String> map = new HashMap<>();
      map.put("msg", "failed");
      failed = new JSONObject(map);
    }
    return failed.toString();
  }
}
